package com.yikome.uaa.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yikome.common.CommonService;
import com.yikome.uaa.domain.Authority;
import com.yikome.uaa.domain.Role;
import com.yikome.uaa.domain.User;
import com.yikome.uaa.po.JwtUserPO;
import com.yikome.uaa.po.ResetMindPassword;
import com.yikome.uaa.po.UserLoginPO;
import com.yikome.uaa.repository.UserRepository;
import com.google.common.base.Preconditions;
import com.itmuch.lightsecurity.jwt.JwtOperator;
import com.itmuch.lightsecurity.jwt.UserOperator;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;

@Service
public class UserService extends CommonService<User, Long> {

	@Autowired
	private UserRepository userRepository ; 
	
	@Autowired
	private NamedParameterJdbcTemplate jdbcTemplate ;
	
	@Autowired
    private UserOperator userOperator;
	
	@Autowired
	private JwtOperator operator;
	
	@Autowired
	public void setResourceDao(UserRepository repository) {
		super.setCommonDao(repository);
	}

	/**
	 * 分页查询用户,包含用户角色,可以通过用户名和角色进行过滤
	 */
	public Page<User> findPageUsers(User userRequest , Pageable pageable) {
		
		String contentSQL = "SELECT  \n" + 
							"	vo.* \n" + 
							"FROM  \n" + 
							"( \n" + 
							"	SELECT   \n" + 
							"		u_user.id , u_user.username , GROUP_CONCAT(u_role.`name`) role_names , u_user.created_at  \n" + 
							"	FROM u_user   \n" + 
							"		LEFT JOIN u_user_role ON (u_user.id = u_user_role.user_id)  \n" + 
							"		LEFT JOIN u_role ON (u_user_role.role_id = u_role.id)  \n" + 
							"	WHERE u_user.yn = 1 \n" + 
							"	GROUP BY u_user.id, u_user.username, u_user.created_at \n" + 
							") vo \n";
		
		Map<String , Object> paramMap = new HashMap<>();
		StringBuilder paramSQL = new StringBuilder("WHERE 1 = 1 \n");
		
		if(StringUtils.isNotBlank(userRequest.getUsername())) {
			paramSQL.append("AND vo.username LIKE :userName \n");
			paramMap.put("userName", "%" + userRequest.getUsername().trim() + "%");
		}
		
		if(StringUtils.isNotBlank(userRequest.getRoleNames())) {
			paramSQL.append("AND vo.role_name LIKE :roleNames \n");
			paramMap.put("roleNames", "%" + userRequest.getRoleNames().trim() + "%");
		}
		
		StringBuilder countSQL = new StringBuilder("SELECT COUNT(1) FROM (").append(contentSQL).append(paramSQL).append(") T") ;
		
		String pageSQL = "   limit " + pageable.getOffset() + " , " + pageable.getPageSize();
		
		List<User> contents = jdbcTemplate.query(contentSQL + paramSQL + pageSQL , paramMap, new BeanPropertyRowMapper<User>(User.class));
		Long total = jdbcTemplate.queryForObject(countSQL.toString(), paramMap, Long.class);
		
		return new PageImpl<>(contents, pageable, total);
	}
	
	public User findUserDetails(Long userId) {
		User user = userRepository.findUser(userId);
		if(user != null) {
			Set<Role> roles = user.getRoles();
			if(roles != null) {
				for (Role role : roles) {
					role.setAuthorities(null);
				}
			}
		}
		return user;
	}

	@Transactional
	public User saveUser(User userRequest) {
		User source = userRepository.findUser(userRequest.getUsername());
		Preconditions.checkArgument(source == null, "同名用户已存在...");
		User user = new User();
		BeanUtil.copyProperties(userRequest, user, "id");
		user.setPassword(SecureUtil.md5(user.getPassword()));
		return userRepository.save(user);
	}

	@Transactional
	public User updateUser(User userRequest) {
		
		User source = userRepository.findUser(userRequest.getId());
		Preconditions.checkArgument(source != null, "对应用户不存在...");
		
		source.getRoles().removeAll(source.getRoles());
		userRepository.save(source);
		
		source.setUsername(userRequest.getUsername());
		source.setRoles(userRequest.getRoles());
		
		return userRepository.save(source);
	}

	public Boolean resetUserPassword(User source) {
		source.setPassword(SecureUtil.md5("123456"));
		userRepository.save(source);
		return true ; 
	}

	@Transactional
	public Boolean resetMindPassword(ResetMindPassword resetMindPasswordRequest) {
		
		com.itmuch.lightsecurity.jwt.User jwtUser = userOperator.getUser();
		Preconditions.checkArgument(jwtUser != null, "登陆用户不存在或超时...");
		User source = userRepository.findUser(jwtUser.getId().longValue());
		Preconditions.checkArgument(source != null, "对应用户不存在...");
		
		Preconditions.checkArgument(StringUtils.equalsIgnoreCase(SecureUtil.md5(resetMindPasswordRequest.getOldPassword()), source.getPassword()), "原密码不正确...");
		source.setPassword(SecureUtil.md5(resetMindPasswordRequest.getNewPassword()));
		
		userRepository.save(source);
		return true;
	}

	@Transactional
	public Boolean deleteUser(User source) {
		userRepository.delete(source);
		
		return true;
	}

	public JwtUserPO login(UserLoginPO userLoginPO) {
		
		User user = userRepository.findUser(userLoginPO.getUsername());
		
		Preconditions.checkArgument(user != null, "用户不存在...");
		
		Preconditions.checkArgument(StringUtils.equalsIgnoreCase(user.getPassword(), SecureUtil.md5(userLoginPO.getPassword())), "密码错误....");
		
		Set<Role> roles = user.getRoles();
		List<String> roleNames = new ArrayList<>();
		
		Set<Authority> authorityNames  = new HashSet<>();
		
		roles.forEach((role) -> {
			roleNames.add(role.getValue());
			Set<Authority> authorities = role.getAuthorities();
			authorityNames.addAll(authorities);
		});
		
		com.itmuch.lightsecurity.jwt.User securityUser = com.itmuch.lightsecurity.jwt.User.builder()
									                .id(user.getId().intValue())
									                .username(user.getUsername())
									                .roles(roleNames)
									                .build();
        String token = operator.generateToken(securityUser);
        
        JwtUserPO jwtUser = JwtUserPO.builder().authorities(new ArrayList<>(authorityNames)).roles(roleNames).token(token).userName(user.getUsername()).build();

        return jwtUser ;
        
	}
	
	public static void main(String[] args) {
		System.out.println(SecureUtil.md5("123456"));
	}
}
